package cn.guetzjb.controller;

import cn.guetzjb.core.constant.CacheConstants;
import cn.guetzjb.core.constant.SecurityConstants;
import cn.guetzjb.core.entity.R;
import cn.guetzjb.core.exception.ServiceException;
import cn.guetzjb.domain.ChangePwdBody;
import cn.guetzjb.domain.LoginBody;
import cn.guetzjb.redis.service.RedisService;
import cn.guetzjb.security.service.TokenService;
import cn.guetzjb.security.utils.SecurityUtils;
import cn.guetzjb.sys.domain.SysLogininfor;
import cn.guetzjb.sys.feign.SysUserFeign;
import cn.guetzjb.sys.model.LoginUser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RequestMapping("/auth")
@RestController
@RequiredArgsConstructor
@RefreshScope
@Tag(name = "认证服务")
public class AuthController {

    private final SysUserFeign sysUserFeign;
    private final TokenService tokenService;
    private final RedisService redisService;

    @Value("${captcha.enable}")
    private boolean captchaEnable;

    @Value("${captcha.type}")
    private String captchaType;

    @Value("${register.enable}")
    private boolean registerEnable;

    @Operation(summary = "登录")
    @PostMapping("/login")
    @Transactional
    public R login(@RequestBody LoginBody loginBody) {
        int status = checkCaptcha(loginBody);
        SysLogininfor sysLogininfor = new SysLogininfor();
        sysLogininfor.setUserName(loginBody.getUsername());
        if (status == -1) {
            sysLogininfor.setMsg("登陆失败，验证码过期");
            sysUserFeign.addLogError(sysLogininfor);
            return R.failed("验证码过期！");
        }
        if (status == -2) {
            sysLogininfor.setMsg("登陆失败，验证码填写错误");
            sysUserFeign.addLogError(sysLogininfor);
            return R.failed("验证码填写错误！");
        }
        LoginUser loginUser = sysUserFeign.info(loginBody.getUsername(), SecurityConstants.INNER).getData();
        if (loginUser == null || !tokenService.checkUsernamePassword(loginUser, loginBody.getPassword())) {
            sysLogininfor.setMsg("登陆失败，账号或者密码错误");
            sysUserFeign.addLogError(sysLogininfor);
            throw new ServiceException("账号或者密码错误！");
        }
        //日记记录
        sysLogininfor.setMsg("登陆成功");
        sysUserFeign.addLogSuccess(sysLogininfor);
        sysUserFeign.addUserLoginInfo(loginUser.getSysUser(), SecurityConstants.INNER);
        //生成token，存入redis
        Map<String, Object> map = tokenService.generateToken(loginUser);
        map.put("sysUser", loginUser.getSysUser());
        return R.ok(map);
    }

    @Operation(summary = "刷新token")
    @PostMapping("/refresh")
    public R refreshToken() {
        LoginUser loginUser = sysUserFeign.info(SecurityUtils.getUsername(), SecurityConstants.INNER).getData();
        sysUserFeign.addUserLoginInfo(loginUser.getSysUser(), SecurityConstants.INNER);
        Map<String, Object> map = tokenService.generateToken(loginUser);
        map.put("sysUser", loginUser.getSysUser());
        return R.ok(map);
    }

    @Operation(summary = "注册")
    @PostMapping("/register")
    public R register(@RequestBody LoginBody loginBody) {
        if (!registerEnable) {
            return R.failed("注册已关闭！");
        }
        int status = checkCaptcha(loginBody);
        if (status == -1) {
            return R.failed("验证码过期！");
        }
        if (status == -2) {
            return R.failed("验证码填写错误！");
        }
        R res = sysUserFeign.register(loginBody.getUsername(), loginBody.getPassword(), SecurityConstants.INNER);
        if (res.getData() == null) {
            throw new ServiceException(res.getMsg());
        }
        return R.ok("注册成功");
    }

    @Operation(summary = "退出登录")
    @PostMapping("/logout")
    public R logout() {
        Long userId = SecurityUtils.getUserId();
        String key = CacheConstants.LOGIN_TOKEN_KEY + userId;
        boolean b = redisService.deleteObject(key);
        SysLogininfor sysLogininfor = new SysLogininfor();
        sysLogininfor.setUserName(SecurityUtils.getUsername());
        if (b) {
            sysLogininfor.setMsg("退出账号");
            sysUserFeign.addLogSuccess(sysLogininfor);
            return R.ok();
        } else {
            return R.failed();
        }
    }

    @Operation(summary = "修改密码(self)")
    @PostMapping("/changePwd")
    public R changePwd(@RequestBody ChangePwdBody changePwdBody) {
        if (!changePwdBody.getPassword().equals(changePwdBody.getConfirmPassword())) {
            return R.failed("两次输入的密码不一致！");
        }
        boolean b = sysUserFeign.changePwd(changePwdBody.getUserName(), changePwdBody.getPassword(), SecurityConstants.INNER);
        if (b) {
            return R.ok("修改密码成功");
        }
        return R.failed("修改密码失败");
    }

    private int checkCaptcha(LoginBody loginBody) {
        if (captchaEnable) {
            String key = CacheConstants.CAPTCHA_CODE_KEY + loginBody.getUuidKey();
            if (!redisService.hasKey(key)) {
                return -1;
            }
            String captchaCode = redisService.getCacheObject(key).toString();
            if (!captchaCode.equals(loginBody.getCaptchaCode())) {
                return -2;
            }
        }
        return 0;
    }

}
